﻿using System;
using System.Collections.Generic;
using System.Text;
using Vortex;
using Vortex.Drawing;
using Vortex.Input;
using System.Drawing;

namespace Vortex.Tutorials.MouseAndKeyboardInput {

    ///<summary>Demonstration of keyboard and mouse input</summary>
    class MouseAndKeyboardInput : Game {
        
        ///<summary>Baloon information call</summary>
        class Balloon {
            public Vector2 Position { set; get; }
            public Vector2 Speed { set; get; }
            public ColorU Color { set; get; }
        }

        //define tutorial constants
        const float BLOW_DISTANCE = 30;
        const float SCREEN_OFFSPACE = 64;
        const float BALLONS_PER_SECOND = 7;
        const float MIN_BALLOON_SPEED = 50;
        const float VAR_BALLOON_SPEED = 150;

        readonly ColorU[] BALOON_COLORS = new ColorU[] { ColorU.White, ColorU.Blue, ColorU.Green, ColorU.Yellow, ColorU.Cyan, ColorU.Red, ColorU.Violet };

        readonly Random _Random = new Random();

        Texture _MountainsTexture;
        Texture _BalloonTexture;
        Texture _CrossHairTexture;

        List<Balloon> _BalloonList = new List<Balloon>();
        float _BalloonsToCreate = 0;
        

        public MouseAndKeyboardInput() {
            Window.Title = "Mouse And Keyboard Input Tutorial - Vortex2D.NET";
            Window.Size = new System.Drawing.Size(1024, 768);
        }

        protected override void Load () {
            _MountainsTexture = new Texture(@"{graphics}\mountains.jpg");
            _BalloonTexture = new Texture(@"{graphics}\balloon.png");
            _CrossHairTexture = new Texture(@"{graphics}\crosshair.png");

            //Setting global mouse event handler
            // Game.Mouse.OnLeftButtonDown += new WindowsMouseEventHandler(this.OnMouseDown);
            //Setting global keyboard event handler
			Game.Keyboard.KeyDown += new KeyActionHandler(this.OnKeyDown);
			Game.Mouse.ButtonDown += new MouseButtonActionHandler(this.OnMouseDown);
        }

        protected override void Unload () {
            _MountainsTexture.Dispose();
            _BalloonTexture.Dispose();
            _CrossHairTexture.Dispose();
        }

        protected override void Update (GameTime time) {
            //Check to swtich some game/display states
            CheckStateSwitchingEvents();

            //For each balloon we need to check go offscreen and calculate position
            foreach (Balloon ballon in _BalloonList.ToArray()) {
                if (ballon.Position.Y < -SCREEN_OFFSPACE) {
                    _BalloonList.Remove(ballon);
                }
                ballon.Position += ballon.Speed * time.FrameTime;
            }

            //create new balloons
            _BalloonsToCreate += BALLONS_PER_SECOND * time.FrameTime;
            int createThisTime = (int)Math.Floor(_BalloonsToCreate);
            if (createThisTime > 0) {
                for (int n = 0; n < createThisTime; ++n) {
                   Balloon newBalloon = new Balloon();
                   newBalloon.Position = new Vector2((float)_Random.NextDouble() * Window.Size.Width, Window.Size.Height + SCREEN_OFFSPACE);
                   newBalloon.Speed = new Vector2(0, MIN_BALLOON_SPEED + (float)_Random.NextDouble() * VAR_BALLOON_SPEED).Negative;
                   newBalloon.Color = BALOON_COLORS[_Random.Next(BALOON_COLORS.Length)];
                   _BalloonList.Add(newBalloon);
                }
                _BalloonsToCreate -= createThisTime;
            }
            
            base.Update(time);
        }

        protected override void Render (Canvas2D canvas) {
            //Draw background
            canvas.DrawSprite(canvas.Region, _MountainsTexture.ToSprite(), ColorU.White);

            //Draw all balloons
            foreach (Balloon balloon in _BalloonList) {
                canvas.DrawSprite(balloon.Position, _BalloonTexture.ToSprite(), balloon.Color.MultiplyAlpha(0.75f));
            }

            //Draw Cross Hair at the top
            if (Mouse.IsOverWindow) {
                canvas.DrawSprite((Vector2)Mouse.Location, _CrossHairTexture.ToSprite(), ColorU.Black);
            }

            //Draw Help Text
            canvas.DrawTextLayout(SpriteFont.Console, canvas.Region, "Alt + Enter - toggle fullscreen\nF2 - toggle FPS counter\nV - toggle vertical synchronization", TextLayout.Left | TextLayout.Bottom, ColorU.White);
        }

        //Blows baloon around some point
        private void BlowBalloonsAround(Vector2 position) {
            foreach (Balloon ballon in _BalloonList.ToArray()) {
                if (position.Distance(ballon.Position) < BLOW_DISTANCE) {
                    _BalloonList.Remove(ballon);
                }
            }
        }

        ///<summary>Method which can cast mouse events</summary>
        private void OnMouseDown(MouseButtonActionInfo info) {
			BlowBalloonsAround((Vector2)info.Location);
        }

        ///<summary>Method which can cast keyboard down/up events</summary>
        private void OnKeyDown (VirtualKey vKey) {
            if (vKey == VirtualKey.V) {
                //Toggling vertical synchronization, device will be reset between frames
                Window.VerticalSync = !Window.VerticalSync;
            }
        }

        ///<summary>This method uses asynchronous reading of keyboard state</summary>
        private void CheckStateSwitchingEvents () {
            //check is F2 button was pressed this frame - enable/disable showing FPS
            if (Keyboard.IsPressed(Key.F2)) {
                //this property enables showing FPS
				Game.Debugging.ShowFPS = !Game.Debugging.ShowFPS;
            }
        }

    }

}
